Skip to content

feat: add github connection#1613

Open
olivermrose wants to merge 19 commits intonpmx-dev:mainfrom
olivermrose:feat/gh-connection
Open

feat: add github connection#1613
olivermrose wants to merge 19 commits intonpmx-dev:mainfrom
olivermrose:feat/gh-connection

Conversation

@olivermrose
Copy link
Contributor

@olivermrose olivermrose commented Feb 23, 2026

🔗 Linked issue

#479

🧭 Context

Implements GitHub OAuth, displays whether a repo is starred or not, and the ability to star/unstar through the UI. This does not implement the search improvements portion.

Demo
demo.mp4

📚 Description

  • .env requires GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET from an OAuth app in order to run. The redirect uri needs to be http://127.0.0.1:3000, not http://localhost:3000. This also needs to be the url that is visited in the browser in order for the cookie to persist properly.
  • I renamed/moved some of the AT Protocol files to distinguish between the auth providers since there's more than one now. I based the GH auth off the existing AT route, and I didn't run into any issues, but it's been a while since I've manually handled oauth flows, so there's a chance I've missed an edge case or something.
  • For the starring API routes, I left them all under /github because I wasn't sure if a /star path was needed/wanted.
  • UNGH caches responses so the star count can't be updated other than an optimistic update, but this won't persist across reloads/navigation.

@vercel
Copy link

vercel bot commented Feb 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Feb 27, 2026 4:59pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Feb 27, 2026 4:59pm
npmx-lunaria Ignored Ignored Feb 27, 2026 4:59pm

Request Review

@github-actions
Copy link

github-actions bot commented Feb 23, 2026

Lunaria Status Overview

🌕 This pull request will trigger status changes.

Learn more

By default, every PR changing files present in the Lunaria configuration's files property will be considered and trigger status changes accordingly.

You can change this by adding one of the keywords present in the ignoreKeywords property in your Lunaria configuration file in the PR's title (ignoring all files) or by including a tracker directive in the merged commit's description.

Tracked Files

File Note
lunaria/files/ar-EG.json Localization changed, will be marked as complete. 🔄️
lunaria/files/az-AZ.json Localization changed, will be marked as complete. 🔄️
lunaria/files/bg-BG.json Localization changed, will be marked as complete. 🔄️
lunaria/files/bn-IN.json Localization changed, will be marked as complete. 🔄️
lunaria/files/cs-CZ.json Localization changed, will be marked as complete. 🔄️
lunaria/files/de-DE.json Localization changed, will be marked as complete. 🔄️
lunaria/files/en-GB.json Localization changed, will be marked as complete. 🔄️
lunaria/files/en-US.json Source changed, localizations will be marked as outdated.
lunaria/files/es-419.json Localization changed, will be marked as complete. 🔄️
lunaria/files/es-ES.json Localization changed, will be marked as complete. 🔄️
lunaria/files/fr-FR.json Localization changed, will be marked as complete. 🔄️
lunaria/files/hi-IN.json Localization changed, will be marked as complete. 🔄️
lunaria/files/id-ID.json Localization changed, will be marked as complete. 🔄️
lunaria/files/it-IT.json Localization changed, will be marked as complete. 🔄️
lunaria/files/ja-JP.json Localization changed, will be marked as complete. 🔄️
lunaria/files/kn-IN.json Localization changed, will be marked as complete. 🔄️
lunaria/files/nb-NO.json Localization changed, will be marked as complete. 🔄️
lunaria/files/ne-NP.json Localization changed, will be marked as complete. 🔄️
lunaria/files/pl-PL.json Localization changed, will be marked as complete. 🔄️
lunaria/files/pt-BR.json Localization changed, will be marked as complete. 🔄️
lunaria/files/ru-RU.json Localization changed, will be marked as complete. 🔄️
lunaria/files/ta-IN.json Localization changed, will be marked as complete. 🔄️
lunaria/files/te-IN.json Localization changed, will be marked as complete. 🔄️
lunaria/files/uk-UA.json Localization changed, will be marked as complete. 🔄️
lunaria/files/zh-CN.json Localization changed, will be marked as complete. 🔄️
lunaria/files/zh-TW.json Localization changed, will be marked as complete. 🔄️
Warnings reference
Icon Description
🔄️ The source for this localization has been updated since the creation of this pull request, make sure all changes in the source have been applied.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds GitHub integration and refactors Atproto auth: introduces useGitHub, useGitHubStar, a GitHub modal component, server GitHub OAuth and session endpoints, server helpers for toggling GitHub stars, and extends the server session with a github field. Moves Atproto session endpoints under /api/auth/atproto/ and updates useAtproto. Updates Header AccountMenu to render per-service modals (Atproto and GitHub), stacked avatars for multiple connections, and replaces the previous auth modal with Atproto/GitHub modals. Also restructures i18n keys by adding atmosphere and github modal blocks across locales and updates related translation files.

Possibly related PRs

Suggested labels

i18n

Suggested reviewers

  • danielroe
🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description is directly related to the changeset, explaining GitHub OAuth implementation, file reorganization for auth providers, and API design decisions.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (3)
shared/schemas/github.ts (1)

3-6: Consider adding non-empty string validation for owner and repo.

v.string() accepts empty strings, which would pass validation but fail silently at the GitHub API level. A minLength(1) pipe rejects these at the schema boundary.

♻️ Suggested fix
 export const GitHubStarBodySchema = v.object({
-  owner: v.string(),
-  repo: v.string(),
+  owner: v.pipe(v.string(), v.minLength(1)),
+  repo: v.pipe(v.string(), v.minLength(1)),
 })
server/api/auth/github/session.delete.ts (1)

3-11: Consider returning a structured JSON response for consistency.

Other endpoints in this PR return JSON objects (e.g., { starred: false }). Returning a plain string here makes it harder for clients to handle responses uniformly. A minor inconsistency, but worth aligning.

Suggested fix
-  return 'GitHub disconnected'
+  return { disconnected: true }
server/api/github/star.put.ts (1)

7-47: Significant code duplication with star.delete.ts.

This handler is nearly identical to star.delete.ts — the only differences are the HTTP method (PUT vs DELETE), the Content-Length header, and the returned starred boolean. Consider extracting a shared helper to reduce duplication:

Sketch of shared helper
// server/utils/github-star.ts
export async function toggleGitHubStar(event: H3Event, method: 'PUT' | 'DELETE') {
  const session = await useServerSession(event)
  const github = session.data.github

  if (!github?.accessToken) {
    throw createError({ statusCode: 401, message: 'GitHub account not connected.' })
  }

  const { owner, repo } = v.parse(GitHubStarBodySchema, await readBody(event))

  // ... validation, fetch, error handling ...

  return { starred: method === 'PUT' }
}

Note: the path traversal concern flagged on star.delete.ts applies equally here.


ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0fd5a7d and 4497ac5.

📒 Files selected for processing (24)
  • app/components/Header/AccountMenu.client.vue
  • app/components/Header/AtprotoModal.client.vue
  • app/components/Header/GitHubModal.client.vue
  • app/composables/atproto/useAtproto.ts
  • app/composables/github/useGitHub.ts
  • app/composables/github/useGitHubStar.ts
  • app/pages/package/[[org]]/[name].vue
  • i18n/locales/en.json
  • i18n/schema.json
  • lunaria/files/en-GB.json
  • lunaria/files/en-US.json
  • nuxt.config.ts
  • server/api/auth/atproto/index.get.ts
  • server/api/auth/atproto/session.delete.ts
  • server/api/auth/atproto/session.get.ts
  • server/api/auth/github/index.get.ts
  • server/api/auth/github/session.delete.ts
  • server/api/auth/github/session.get.ts
  • server/api/github/star.delete.ts
  • server/api/github/star.put.ts
  • server/api/github/starred.get.ts
  • server/utils/auth.ts
  • shared/schemas/github.ts
  • shared/types/userSession.ts

@serhalp serhalp linked an issue Feb 23, 2026 that may be closed by this pull request
@serhalp serhalp added the social Social features label Feb 23, 2026
@olivermrose

This comment was marked as resolved.

@olivermrose olivermrose marked this pull request as draft February 23, 2026 20:48
@olivermrose

This comment was marked as resolved.

@olivermrose olivermrose marked this pull request as ready for review February 27, 2026 16:29
@codecov
Copy link

codecov bot commented Feb 27, 2026

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

♻️ Duplicate comments (1)
server/api/auth/atproto/session.delete.ts (1)

5-9: ⚠️ Potential issue | 🟠 Major

Use explicit key deletion for session cleanup (Line 5).

serverSession.update({ ...: undefined }) can leave stale session keys instead of removing them, which weakens sign-out cleanup.

Suggested fix
-  await serverSession.update({
-    public: undefined,
-    oauthSession: undefined,
-    oauthState: undefined,
-  })
+  await serverSession.update((data) => {
+    delete data.public
+    delete data.oauthSession
+    delete data.oauthState
+  })
In h3 sessions (as used by Nuxt 4.3.1), does `session.update({ key: undefined })` delete the key or keep it with an undefined value? Please provide the official documentation/source behaviour for `updateSession`.
🧹 Nitpick comments (1)
lunaria/files/ta-IN.json (1)

848-848: Consider aligning connected_as phrasing with the Atmosphere string pattern.

Line 848 uses a different word order from Line 836. Keeping both in the same placeholder order will make the modal copy more consistent.

Suggested tweak
-        "connected_as": "ஆக இணைக்கப்பட்டது {username}"
+        "connected_as": "{username} ஆக இணைக்கப்பட்டது"

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 61dd36f and d9a47bc.

📒 Files selected for processing (72)
  • app/components/Header/AccountMenu.client.vue
  • app/components/Header/AtprotoModal.client.vue
  • app/components/Header/GitHubModal.client.vue
  • app/composables/atproto/useAtproto.ts
  • app/composables/github/useGitHub.ts
  • app/composables/github/useGitHubStar.ts
  • app/pages/package/[[org]]/[name].vue
  • i18n/locales/ar.json
  • i18n/locales/az-AZ.json
  • i18n/locales/bg-BG.json
  • i18n/locales/bn-IN.json
  • i18n/locales/cs-CZ.json
  • i18n/locales/de-DE.json
  • i18n/locales/en.json
  • i18n/locales/es.json
  • i18n/locales/fr-FR.json
  • i18n/locales/hi-IN.json
  • i18n/locales/id-ID.json
  • i18n/locales/it-IT.json
  • i18n/locales/ja-JP.json
  • i18n/locales/kn-IN.json
  • i18n/locales/nb-NO.json
  • i18n/locales/ne-NP.json
  • i18n/locales/pl-PL.json
  • i18n/locales/pt-BR.json
  • i18n/locales/ru-RU.json
  • i18n/locales/ta-IN.json
  • i18n/locales/te-IN.json
  • i18n/locales/uk-UA.json
  • i18n/locales/zh-CN.json
  • i18n/locales/zh-TW.json
  • i18n/schema.json
  • lunaria/files/ar-EG.json
  • lunaria/files/az-AZ.json
  • lunaria/files/bg-BG.json
  • lunaria/files/bn-IN.json
  • lunaria/files/cs-CZ.json
  • lunaria/files/de-DE.json
  • lunaria/files/en-GB.json
  • lunaria/files/en-US.json
  • lunaria/files/es-419.json
  • lunaria/files/es-ES.json
  • lunaria/files/fr-FR.json
  • lunaria/files/hi-IN.json
  • lunaria/files/id-ID.json
  • lunaria/files/it-IT.json
  • lunaria/files/ja-JP.json
  • lunaria/files/kn-IN.json
  • lunaria/files/nb-NO.json
  • lunaria/files/ne-NP.json
  • lunaria/files/pl-PL.json
  • lunaria/files/pt-BR.json
  • lunaria/files/ru-RU.json
  • lunaria/files/ta-IN.json
  • lunaria/files/te-IN.json
  • lunaria/files/uk-UA.json
  • lunaria/files/zh-CN.json
  • lunaria/files/zh-TW.json
  • nuxt.config.ts
  • server/api/auth/atproto/index.get.ts
  • server/api/auth/atproto/session.delete.ts
  • server/api/auth/atproto/session.get.ts
  • server/api/auth/github/index.get.ts
  • server/api/auth/github/session.delete.ts
  • server/api/auth/github/session.get.ts
  • server/api/github/star.delete.ts
  • server/api/github/star.put.ts
  • server/api/github/starred.get.ts
  • server/utils/auth.ts
  • server/utils/github.ts
  • shared/schemas/github.ts
  • shared/types/userSession.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • shared/schemas/github.ts
  • app/components/Header/GitHubModal.client.vue
  • server/utils/auth.ts
  • server/api/github/star.put.ts
  • server/api/github/starred.get.ts
  • nuxt.config.ts
  • server/api/github/star.delete.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

social Social features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

github connection

2 participants